package mahan.test.data.mongodb;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import mahan.data.model.Product;
import mahan.data.model.Vendor;
import mahan.data.mongodb.MahanDB;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import com.mongodb.BasicDBObject;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
import com.mongodb.DBObject;

public class ShoeTestCase {
	private MahanDB mahanDb;

	private void clean() {
		mahanDb.get().dropDatabase();
	}

	private Product createAdidas() {
		Product shoe = new Product("ADIDAS", "ADIDAS Awesome", 2);
		shoe.setProductID(2);
		return shoe;
	}

	private Product createNike() {
		Product shoe = new Product("NIKE", "Nike Air", 1);
		shoe.setProductID(1);
		return shoe;
	}

	@Before
	public void setup() {
		mahanDb = new MahanDB("localhost", 27017, "mydb");
		DB db = mahanDb.get();
		assertNotNull(db);
	}

	@After
	public void tearDown() {
		clean();
	}

	@SuppressWarnings("unchecked")
	@Test
	public void testShoe() throws Exception {
		clean();
		String collectionName = "ShoeCollection";
		DBCollection shoeCollection = mahanDb.createCollection(collectionName);
		assertNotNull(shoeCollection);
		Vendor vendor = new Vendor(1, "Nike");
		BasicDBObject vendorDB = new BasicDBObject(vendor.get());

		shoeCollection.save(vendorDB);

		Product nike = createNike();
		BasicDBObject nikeDB = new BasicDBObject(nike.get());
		shoeCollection.save(nikeDB);

		Product adidas = createAdidas();
		BasicDBObject adidasDB = new BasicDBObject(adidas.get());
		shoeCollection.save(adidasDB);

		shoeCollection.save(adidasDB);// No need to reinsert

		// Let us search
		DBCursor cursor = shoeCollection.find(nikeDB);
		assertEquals(1, cursor.count());
		DBObject dbObj = cursor.next();
		assertTrue(dbObj instanceof BasicDBObject);
		Product fromNike = Product.instance();
		fromNike.put(dbObj.toMap());
		assertEquals(nike.getProductID(), fromNike.getProductID());
		assertEquals(nike.getVendorID(), fromNike.getVendorID());
		cursor.close();

		// Search again now with BasicDBObject
		BasicDBObject bd = new BasicDBObject();
		bd.putAll(nike.get());
		cursor = shoeCollection.find(bd);
		assertEquals(1, cursor.count());
		dbObj = cursor.next();
		assertTrue(dbObj instanceof BasicDBObject);
		assertEquals(nike.getProductID(), dbObj.get("pid"));
		assertEquals(nike.getVendorID(), dbObj.get("vid"));
		cursor.close();

		// Let us search for adidas by product id
		bd = new BasicDBObject();
		bd.put("pid", new BasicDBObject("$gt", 1));
		cursor = shoeCollection.find(bd);
		assertEquals(1, cursor.count());
		dbObj = cursor.next();
		assertTrue(dbObj instanceof BasicDBObject);
		assertEquals(adidas.getProductID(), dbObj.get("pid"));
		assertEquals(adidas.getVendorID(), dbObj.get("vid"));
		cursor.close();

		// Let us search for adidas by vendor id
		bd = new BasicDBObject();
		bd.put("vid", 2);
		cursor = shoeCollection.find(bd);
		assertEquals(1, cursor.count());
		dbObj = cursor.next();
		assertTrue(dbObj instanceof BasicDBObject);
		assertEquals(adidas.getProductID(), dbObj.get("pid"));
		assertEquals(adidas.getVendorID(), dbObj.get("vid"));
		cursor.close();
	}
}